package com.koron.common.core.util.dfs;

import com.alibaba.fastjson.util.Base64;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.exception.FdfsServerException;
import com.github.tobato.fastdfs.exception.FdfsUnsupportStorePathException;
import com.github.tobato.fastdfs.service.DefaultAppendFileStorageClient;
import com.github.tobato.fastdfs.service.DefaultFastFileStorageClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;


/**
 * @author twcao
 */
@Slf4j
@Component
public class FastDFSClientWrapper {

    @Autowired
    private DefaultFastFileStorageClient storageClient;

    @Autowired
    private DefaultAppendFileStorageClient fileStorageClient;

    /**
     * 上传文件
     *
     * @param file 文件对象
     * @return 文件访问地址
     * @throws IOException
     */
    public String uploadFile(MultipartFile file) throws IOException {
        return uploadFile(file.getInputStream(), file.getSize(), FilenameUtils.getExtension(file.getOriginalFilename()));
    }

    /**
     * 上传文件流
     *
     * @param inputStream 文件流
     * @param fileSize    文件大小
     * @param fileExtName 文件后缀
     * @return 文件地址
     */
    public String uploadFile(InputStream inputStream, long fileSize, String fileExtName) {
        StorePath storePath = storageClient.uploadFile(inputStream, fileSize, fileExtName, null);
        return getResAccessUrl(storePath);
    }

    /**
     * 上传追加文件
     *
     * @param groupName   组名
     * @param inputStream 文件流
     * @param fileSize    文件大小
     * @param fileExtName 文件后缀
     * @return 文件地址
     */
    public String uploadAppenderFile(String groupName, InputStream inputStream, long fileSize, String fileExtName) {
        StorePath storePath = fileStorageClient.uploadAppenderFile(groupName, inputStream, fileSize, fileExtName);
        return getResAccessUrl(storePath);
    }

    /**
     * 追加文件流
     *
     * @param groupName   组名
     * @param path        文件路径
     * @param inputStream 文件流
     * @param fileSize    文件大小
     * @return 文件地址
     */
    public void appendFile(String groupName, String path, InputStream inputStream, long fileSize) {
        fileStorageClient.appendFile(groupName, path, inputStream, fileSize);
    }

    /**
     * 将一段字符串生成一个文件上传
     *
     * @param content       文件内容
     * @param fileExtension 文件后缀
     * @return 返回文件路径
     */
    public String uploadFile(String content, String fileExtension) {
        byte[] buff = content.getBytes(Charset.forName("UTF-8"));
        ByteArrayInputStream stream = new ByteArrayInputStream(buff);
        StorePath storePath = storageClient.uploadFile(stream, buff.length, fileExtension, null);
        return getResAccessUrl(storePath);
    }

    /**
     * 将base64编码字符串转换为图片
     *
     * @param pic           文件base64上传至文件服务器
     * @param fileExtension 文件后缀
     * @return 附件地址
     */
    public String uploadImage(String pic, String fileExtension) {
        byte[] buff = Base64.decodeFast(pic);
        for (int i = 0; i < buff.length; ++i) {
            if (buff[i] < 0) {
                // 调整异常数据
                buff[i] += 256;
            }
        }
        ByteArrayInputStream stream = new ByteArrayInputStream(buff);
        StorePath storePath = storageClient.uploadFile(stream, buff.length, fileExtension, null);
        return getResAccessUrl(storePath);
    }

    /**
     * 封装图片完整URL地址
     *
     * @param storePath
     * @return
     */
    private String getResAccessUrl(StorePath storePath) {
        String fileUrl = storePath.getFullPath();
        return fileUrl;
    }

    /**
     * 下载fdfs文件(不建议使用此方法下载过大的文件)
     *
     * @param fileUrl 文件url
     * @return 文件流
     */
    public byte[] download(String fileUrl) {
        StorePath storePath = StorePath.parseFromUrl(fileUrl);
        return storageClient.downloadFile(storePath.getGroup(), storePath.getPath(), IOUtils::toByteArray);
    }

    /**
     * 删除文件
     *
     * @param fileUrl 文件访问地址
     * @return
     */
    public void deleteFile(String fileUrl) {
        if (StringUtils.isEmpty(fileUrl)) {
            return;
        }
        try {
            StorePath storePath = StorePath.parseFromUrl(fileUrl);
            storageClient.deleteFile(storePath.getGroup(), storePath.getPath());
        } catch (FdfsUnsupportStorePathException e) {
            log.warn(e.getMessage());
        } catch (FdfsServerException fdfsServerException) {
            log.warn(fdfsServerException.getMessage());
        }
    }

}
